package top.itpath.admin.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import top.itpath.admin.dto.UserInfo;
import top.itpath.admin.entity.SysRole;
import top.itpath.admin.entity.SysUser;
import top.itpath.admin.mapper.SysUserMapper;
import top.itpath.admin.service.ISysRoleMenuService;
import top.itpath.admin.service.ISysUserRoleService;
import top.itpath.admin.service.IUserService;
import top.itpath.common.BaseModel;
import top.itpath.common.event.UpdateRoleMenuEvent;
import top.itpath.common.event.UpdateUserRoleEvent;
import top.itpath.common.util.PasswordUtil;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zhaomengru
 * create by  2023/10/10 - 16:13
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements IUserService {

    private final ISysUserRoleService sysUserRoleService;
    private final ISysRoleMenuService sysRoleMenuService;

    @Override
    public SysUser register(SysUser user) {
        Assert.notNull(user.getUsername(), "用户名不能为空");
        Assert.notNull(user.getPassword(), "密码不能为空");
        SysUser byUsername = findByUsername(user.getUsername());
        Assert.isNull(byUsername, "用户名已存在");
        String salt = RandomUtil.randomString(10);
        user.setPassword(PasswordUtil.encrypt(user.getPassword(), salt));
        user.setSalt(salt);
        save(user);
        return user;
    }

    @Override
    public SysUser findByUsername(String username) {
        return lambdaQuery().eq(SysUser::getUsername, username).one();
    }

    @Override
    @Cacheable(value = "user-info", key = "#userId", unless = "#result == null")
    public UserInfo getUserInfo(Long userId) {
        Optional<SysUser> user = this.getOptById(userId);
        if (user.isPresent()) {
            UserInfo userInfo = new UserInfo();
            userInfo.setId(user.get().getId());
            userInfo.setUsername(user.get().getUsername());
            List<SysRole> sysRoles = sysUserRoleService.listUserRole(userId);
            userInfo.setRoles(sysRoles);
            Set<Long> roleIds = sysRoles.stream().map(BaseModel::getId).collect(Collectors.toSet());
            userInfo.setPermissions(sysRoleMenuService.listRolePermissions(roleIds));
            return userInfo;
        }
        return null;
    }

    @EventListener
    @Caching(evict = {
            @CacheEvict(value = "user-info", key = "#event.sysUser.id", condition = "#event.sysUser != null")
    })
    public void updateUserRoleEventListener(UpdateUserRoleEvent event) {
        log.info("clean cache :{}", "user-info");
    }

    @EventListener
    @Caching(evict = {
            @CacheEvict(value = "user-info", allEntries = true)
    })
    public void updateRoleMenuEventListener(UpdateRoleMenuEvent event) {
        log.info("clean cache :{}", "user-info");
    }
}